package com.kaochong.xcx.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.kaochong.xcx.cache.FormIdCache;
import com.kaochong.xcx.cache.WechatAccessTokenCache;
import com.kaochong.xcx.common.constant.CommonConstant;
import com.kaochong.xcx.enums.ResultEnum;
import com.kaochong.xcx.exception.KaoChongException;
import com.kaochong.xcx.lock.RedisLock;
import com.kaochong.xcx.pojo.model.FriendHelpTemplate;
import com.kaochong.xcx.pojo.model.TemplateData;
import com.kaochong.xcx.pojo.model.WxAuthModel;
import com.kaochong.xcx.pojo.model.WxTemplate;
import com.kaochong.xcx.properties.WechatAccountProperties;
import com.kaochong.xcx.utils.JsonUtil;
import com.kaochong.xcx.utils.RestTemplateUtils;

import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.util.HashMap;
import java.util.Map;

import lombok.extern.slf4j.Slf4j;

/**
 * @author han
 * @date 2018-05-07 17:17
 */
@Slf4j
@Service
public class WechatServiceImpl {
	
	@Autowired
	WechatAccessTokenCache wechatAccessTokenCache;
	
	@Autowired
	RedisLock redisLock;
	
	private final static Integer exprice = 10000;
	
	public String getAccessToken(String token) {
		String accessToken=null;
		boolean isLock = false;
		String value = (System.currentTimeMillis() + exprice) + "";
		try {
			isLock = redisLock.lock(this.getClass().getName(), value);
			if (isLock) {
				if (StringUtils.isNotBlank(token)) {
					if (!CommonConstant.ACCESS_TOKEN_PASSWORD.equals(token)) {
						throw new KaoChongException(ResultEnum.AUTHENTICATION_FAIL_ERROR);
					}
					accessToken = getAccess();
				} else {
					accessToken = wechatAccessTokenCache.getAccessToken();
					if (StringUtils.isBlank(accessToken)) {
						accessToken = getAccess();
					}
				}
			}
		} catch(Exception e) {
			log.error(e.getMessage(), e);
			throw new KaoChongException(ResultEnum.SERVER_ERROR.getCode(), e.getMessage());
		} finally {
			if (isLock) {
				try {
					redisLock.unlock(this.getClass().getName(), value);
				} catch(Exception e) {
					log.error(e.getMessage(), e);
					throw new KaoChongException(ResultEnum.SERVER_ERROR.getCode(), e.getMessage());
				}
			}
		}
		return accessToken;
	}
	
	private String getAccess() {
		String accessTokenUrl = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s";
		
		accessTokenUrl = String.format(accessTokenUrl, WechatAccountProperties.mpAppId,
				WechatAccountProperties.mpAppSecret);
		RestTemplate restTemplate = new RestTemplate();
		String response = restTemplate.getForObject(accessTokenUrl, String.class);
		
		WxAuthModel object = JSONObject.parseObject(response).toJavaObject(WxAuthModel.class);
		if (null != object.getErrCode()) {
			log.error("【获取accessToken】response={}", response);
			throw new KaoChongException(object.getErrCode(), object.getErrMsg());
		}
		String accessToken = object.getAccessToken();
		wechatAccessTokenCache.setAccessToken(accessToken);
		return accessToken;
	}
	
	@Autowired
	FormIdCache formIdCache;
	
	/**
	 * 发送好友助力解锁成功模板消息
	 * @param template
	 */
	public void sendLockSuccessTemplate(FriendHelpTemplate template) {
		String url = "https://api.weixin.qq.com/cgi-bin/message/wxopen/template/send?access_token=%s";
		
		String accessToken = getAccessToken(null);
		url = String.format(url, accessToken);
		
		WxTemplate message = new WxTemplate();
		message.setTouser(template.getOpenId());
		message.setTemplate_id(WechatAccountProperties.templateId);
		message.setPage(WechatAccountProperties.templatePage);
		message.setForm_id(template.getFormId());
		Map<String, TemplateData> m = new HashMap<>();
		m.put("keyword1", new TemplateData(template.getKeyword1()));
		m.put("keyword2", new TemplateData(template.getKeyword2()));
		message.setData(m);
		String paramJson = JsonUtil.toJson(message);
		
		String response = RestTemplateUtils.post(url, paramJson);
		Map<String, Object> map = JsonUtil.toObject(response, Map.class);
		Integer errcode = (Integer) map.get("errcode");
		if (errcode != 0 ) {
			log.error("【背单词-助力模板消息】errorMsg，request={}, response={}", JsonUtil.toGson(message),
					JsonUtil.toGson(response));
			// 41028 formId不正确，或者过期
			// 41029 formId已被使用
			if(errcode == 41028 || errcode == 41029){
				String formId = formIdCache.getValidFormId(template.getOpenId());
				if (StringUtils.isNotBlank(formId)) {
					template.setFormId(formId);
					sendLockSuccessTemplate(template);
				}
			}
		} else {
			log.info("【背单词-助力模板消息】template send success");
		}
	}
}
